<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>波纹数字</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            font-family: 'Segoe UI', 'Microsoft YaHei', sans-serif;
        }
        
        body {
            background: linear-gradient(135deg, #6a11cb 0%, #2575fc 100%);
            min-height: 100vh;
            display: flex;
            justify-content: center;
            align-items: center;
            padding: 20px;
            color: #333;
        }
        
        .container {
            width: 100%;
            max-width: 850px;
            background: rgba(255, 255, 255, 0.95);
            border-radius: 20px;
            box-shadow: 0 15px 30px rgba(0, 0, 0, 0.2);
            overflow: hidden;
            backdrop-filter: blur(10px);
        }
        
        .content {
            display: flex;
            flex-wrap: wrap;
            padding: 30px;
            gap: 30px;
        }
        
        .controls {
            flex: 1;
            min-width: 280px;
            display: flex;
            flex-direction: column;
            gap: 25px;
        }
        
        .control-group {
            background: white;
            border-radius: 12px;
            padding: 20px;
            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.05);
            border: 1px solid #eaeaea;
        }
        
        .control-title {
            display: flex;
            align-items: center;
            gap: 10px;
            margin-bottom: 15px;
            font-weight: 600;
            color: #2c3e50;
            font-size: 1.1rem;
        }
        
        .control-title svg {
            width: 22px;
            height: 22px;
        }
        
        .input-group {
            margin-bottom: 15px;
        }
        
        label {
            display: block;
            margin-bottom: 8px;
            font-weight: 500;
            color: #555;
        }
        
        input[type="number"] {
            width: 100%;
            padding: 12px 15px;
            border: 1px solid #ddd;
            border-radius: 8px;
            font-size: 1rem;
            transition: all 0.3s;
        }
        
        input[type="number"]:focus {
            border-color: #3498db;
            box-shadow: 0 0 0 3px rgba(52, 152, 219, 0.2);
            outline: none;
        }
        
        .color-preview {
            display: flex;
            align-items: center;
            gap: 15px;
        }
        
        input[type="color"] {
            width: 60px;
            height: 50px;
            border: none;
            border-radius: 8px;
            cursor: pointer;
            background: none;
        }
        
        .color-value {
            font-weight: 500;
            background: #f8f9fa;
            padding: 8px 12px;
            border-radius: 6px;
            font-family: monospace;
            border: 1px solid #ddd;
            transition: all 0.3s;
            width: 100px;
            text-align: center;
        }
        
        .color-value:focus {
            border-color: #3498db;
            box-shadow: 0 0 0 3px rgba(52, 152, 219, 0.2);
            outline: none;
        }
        
        .range-container {
            display: flex;
            align-items: center;
            gap: 15px;
        }
        
        input[type="range"] {
            flex: 1;
            height: 8px;
            border-radius: 4px;
            background: #e0e0e0;
            outline: none;
            -webkit-appearance: none;
        }
        
        input[type="range"]::-webkit-slider-thumb {
            -webkit-appearance: none;
            width: 22px;
            height: 22px;
            border-radius: 50%;
            background: #3498db;
            cursor: pointer;
            box-shadow: 0 2px 5px rgba(0,0,0,0.2);
        }
        
        .size-value {
            font-weight: 600;
            color: #3498db;
            min-width: 60px;
            text-align: center;
            background: #f8f9fa;
            padding: 8px 12px;
            border-radius: 6px;
        }
        
        .preview-container {
            flex: 1;
            min-width: 300px;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            gap: 20px;
        }
        
        .canvas-wrapper {
            background: white;
            border-radius: 12px;
            padding: 20px;
            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.05);
            border: 1px solid #eaeaea;
            display: flex;
            justify-content: center;
            align-items: center;
        }
        
        .preview {
            position: relative;
            width: 200px;
            height: 200px;
            display: flex;
            justify-content: center;
            align-items: center;
        }
        
        .center-circle {
            width: 100px;
            height: 100px;
            border-radius: 50%;
            background: #3498db;
            display: flex;
            justify-content: center;
            align-items: center;
            color: white;
            font-size: 40px;
            font-weight: bold;
            z-index: 10;
            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
        }
        
        .ripple {
            position: absolute;
            width: 100%;
            height: 100%;
            border-radius: 50%;
            border: 2px solid #3498db;
            animation: ripple 2s infinite linear;
            clip-path: circle(50%);
        }
        
        /* 不同形状的波纹 */
        .ripple.shape-square {
            border-radius: 0;
            clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%);
        }
        
        .ripple.shape-triangle {
            border-radius: 0;
            clip-path: polygon(50% 0%, 0% 100%, 100% 100%);
        }
        
        
        
        .ripple.shape-hexagon {
            border-radius: 0;
            clip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);
        }
        
        /* 形状选择器样式 */
        .shape-option {
            width: 60px;
            height: 60px;
            display: flex;
            justify-content: center;
            align-items: center;
            cursor: pointer;
            border-radius: 8px;
            transition: all 0.3s;
            border: 2px solid transparent;
        }
        
        .shape-option:hover {
            background-color: #f0f7ff;
            transform: translateY(-2px);
        }
        
        .shape-option.active {
            border-color: #3498db;
            background-color: #f0f7ff;
            box-shadow: 0 0 0 3px rgba(52, 152, 219, 0.2);
        }
        
        .ripple-2 {
            animation-delay: 0.66s;
        }
        
        .ripple-3 {
            animation-delay: 1.33s;
        }
        
        @keyframes ripple {
            0% {
                transform: scale(0.5);
                opacity: 1;
            }
            100% {
                transform: scale(1.2);
                opacity: 0;
            }
        }
        
        .action-buttons {
            display: flex;
            gap: 15px;
        }
        
        .export-btn, .copy-btn {
            background: linear-gradient(to right, #2ecc71, #1abc9c);
            color: white;
            border: none;
            border-radius: 8px;
            padding: 14px;
            font-size: 1.1rem;
            font-weight: 600;
            cursor: pointer;
            transition: all 0.3s;
            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
            display: flex;
            align-items: center;
            justify-content: center;
            width: 60px;
            height: 60px;
        }
        
        .copy-btn {
            background: linear-gradient(to right, #3498db, #2980b9);
        }
        
        .export-btn:hover, .copy-btn:hover {
            transform: translateY(-3px);
            box-shadow: 0 8px 20px rgba(0, 0, 0, 0.15);
        }
        
        .export-btn:active, .copy-btn:active {
            transform: translateY(0);
        }
        
        .notification {
            position: fixed;
            top: 20px;
            right: 20px;
            background: rgba(46, 204, 113, 0.9);
            color: white;
            padding: 15px 25px;
            border-radius: 8px;
            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
            z-index: 1000;
            transform: translateX(120%);
            transition: transform 0.3s ease;
            display: flex;
            align-items: center;
            gap: 10px;
        }
        
        .notification.show {
            transform: translateX(0);
        }
        
        .notification.error {
            background: rgba(231, 76, 60, 0.9);
        }
        
        @media (max-width: 768px) {
            .content {
                flex-direction: column;
            }
            
            .preview {
                width: 180px;
                height: 180px;
            }
            
            .center-circle {
                width: 90px;
                height: 90px;
                font-size: 36px;
            }
        }
        
        @media (max-width: 480px) {
            .preview {
                width: 150px;
                height: 150px;
            }
            
            .center-circle {
                width: 75px;
                height: 75px;
                font-size: 30px;
            }
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="content">
            <div class="controls">
                <div class="control-group">
                    <div class="control-title">
                        <svg width="22" height="22" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                            <path d="M4 4H20V20H4V4Z" stroke="#2c3e50" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                            <path d="M9 9H15V15H9V9Z" stroke="#2c3e50" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                            <path d="M9 4V20" stroke="#2c3e50" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                            <path d="M15 4V20" stroke="#2c3e50" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                        </svg>
                        <span>数字设置</span>
                    </div>
                    <div class="input-group">
                        <label for="numInput">数字 (1-99)</label>
                        <input type="number" id="numInput" value="1" min="1" max="99">
                    </div>
                </div>
                
                <div class="control-group">
                    <div class="control-title">
                        <svg width="22" height="22" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                            <path d="M12 2C13.1 2 14 2.9 14 4C14 5.1 13.1 6 12 6C10.9 6 10 5.1 10 4C10 2.9 10.9 2 12 2Z" fill="#2c3e50"/>
                            <path d="M17.89 8.11C17.5 7.72 16.83 7.72 16.44 8.11C16.05 8.5 16.05 9.17 16.44 9.56C16.83 9.95 17.5 9.95 17.89 9.56C18.28 9.17 18.28 8.5 17.89 8.11Z" fill="#2c3e50"/>
                            <path d="M6.42 8.11C6.03 7.72 5.36 7.72 4.97 8.11C4.58 8.5 4.58 9.17 4.97 9.56C5.36 9.95 6.03 9.95 6.42 9.56C6.81 9.17 6.81 8.5 6.42 8.11Z" fill="#2c3e50"/>
                            <path d="M3 13C3 11.9 3.9 11 5 11C6.1 11 7 11.9 7 13C7 14.1 6.1 15 5 15C3.9 15 3 14.1 3 13Z" fill="#2c3e50"/>
                            <path d="M21 13C21 11.9 21.9 11 23 11C24.1 11 25 11.9 25 13C25 14.1 24.1 15 23 15C21.9 15 21 14.1 21 13Z" fill="#2c3e50"/>
                            <path d="M8 16C8 18.21 9.79 20 12 20C14.21 20 16 18.21 16 16C16 13.79 14.21 12 12 12C9.79 12 8 13.79 8 16Z" fill="#2c3e50"/>
                        </svg>
                        <span>颜色设置</span>
                    </div>
                    <div class="color-preview">
                        <input type="color" id="colorInput" value="#3498db">
                        <input type="text" id="colorValue" class="color-value" value="#3498db" maxlength="7" placeholder="#RRGGBB">
                    </div>
                </div>
                
                <div class="control-group">
                    <div class="control-title">
                        <svg width="22" height="22" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                            <path d="M3 3H21V21H3V3Z" stroke="#2c3e50" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                            <path d="M9 9H15V15H9V9Z" stroke="#2c3e50" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                            <path d="M3 9H9" stroke="#2c3e50" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                            <path d="M15 9H21" stroke="#2c3e50" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                            <path d="M3 15H9" stroke="#2c3e50" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                            <path d="M15 15H21" stroke="#2c3e50" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                        </svg>
                        <span>尺寸设置</span>
                    </div>
                    <div class="input-group">
                        <label for="sizeInput">尺寸: <span id="sizeDisplay" class="size-value">40px</span></label>
                        <div class="range-container">
                            <input type="range" id="sizeInput" min="20" max="300" value="40">
                        </div>
                    </div>
                </div>
                
                <div class="control-group">
                    <div class="control-title">
                        <svg width="22" height="22" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                            <path d="M12 2C13.1 2 14 2.9 14 4C14 5.1 13.1 6 12 6C10.9 6 10 5.1 10 4C10 2.9 10.9 2 12 2Z" fill="#2c3e50"/>
                            <path d="M17.89 8.11C17.5 7.72 16.83 7.72 16.44 8.11C16.05 8.5 16.05 9.17 16.44 9.56C16.83 9.95 17.5 9.95 17.89 9.56C18.28 9.17 18.28 8.5 17.89 8.11Z" fill="#2c3e50"/>
                            <path d="M6.42 8.11C6.03 7.72 5.36 7.72 4.97 8.11C4.58 8.5 4.58 9.17 4.97 9.56C5.36 9.95 6.03 9.95 6.42 9.56C6.81 9.17 6.81 8.5 6.42 8.11Z" fill="#2c3e50"/>
                            <path d="M3 13C3 11.9 3.9 11 5 11C6.1 11 7 11.9 7 13C7 14.1 6.1 15 5 15C3.9 15 3 14.1 3 13Z" fill="#2c3e50"/>
                            <path d="M21 13C21 11.9 21.9 11 23 11C24.1 11 25 11.9 25 13C25 14.1 24.1 15 23 15C21.9 15 21 14.1 21 13Z" fill="#2c3e50"/>
                            <path d="M8 16C8 18.21 9.79 20 12 20C14.21 20 16 18.21 16 16C16 13.79 14.21 12 12 12C9.79 12 8 13.79 8 16Z" fill="#2c3e50"/>
                        </svg>
                        <span>波纹形状</span>
                    </div>
                    <div class="shape-options" style="display: flex; gap: 15px; flex-wrap: wrap;">
                        <div class="shape-option active" data-shape="circle" title="圆形">
                            <svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
                                <circle cx="20" cy="20" r="15" stroke="#3498db" stroke-width="2" fill="none"/>
                            </svg>
                        </div>
                        <div class="shape-option" data-shape="square" title="方形">
                            <svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
                                <rect x="5" y="5" width="30" height="30" stroke="#3498db" stroke-width="2" fill="none"/>
                            </svg>
                        </div>
                        <div class="shape-option" data-shape="triangle" title="三角形">
                            <svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
                                <path d="M20 5L35 35L5 35L20 5Z" stroke="#3498db" stroke-width="2" fill="none"/>
                            </svg>
                        </div>
                        <div class="shape-option" data-shape="hexagon" title="六边形">
                            <svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
                                <path d="M20 2L33 10L33 29L20 38L7 29L7 10L20 2Z" stroke="#3498db" stroke-width="2" fill="none"/>
                            </svg>
                        </div>
                    </div>
                </div>
            </div>
            
            <div class="preview-container">
                <div class="canvas-wrapper">
                    <div class="preview" id="preview">
                        <div class="ripple"></div>
                        <div class="ripple ripple-2"></div>
                        <div class="ripple ripple-3"></div>
                        <div class="center-circle" id="centerCircle">1</div>
                    </div>
                </div>
                
                </div>
            
            <div class="action-buttons" style="position: fixed; right: 30px; top: 50%; transform: translateY(-50%); flex-direction: column;">
                <button id="copyBtn" class="copy-btn" title="复制SVG代码">
                    <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                        <path d="M14 2H6C4.9 2 4 2.9 4 4V20C4 21.1 4.9 22 6 22H18C19.1 22 20 21.1 20 20V8L14 2Z" fill="white"/>
                        <path d="M14 2V8H20" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                        <path d="M16 13H8" stroke="white" stroke-width="2" stroke-linecap="round"/>
                        <path d="M16 17H8" stroke="white" stroke-width="2" stroke-linecap="round"/>
                        <path d="M10 9H9H8" stroke="white" stroke-width="2" stroke-linecap="round"/>
                    </svg>
                </button>
                
                <button id="exportBtn" class="export-btn" title="导出图片" style="margin-top: 15px;">
                    <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                        <path d="M12 16L12 8" stroke="white" stroke-width="2" stroke-linecap="round"/>
                        <path d="M9 11L12 8L15 11" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                        <path d="M8 16H16" stroke="white" stroke-width="2" stroke-linecap="round"/>
                        <rect x="4" y="4" width="16" height="16" rx="2" stroke="white" stroke-width="2"/>
                    </svg>
                </button>
            </div>
            </div>
        </div>
    </div>
    
    <div id="notification" class="notification">
        <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
            <path d="M22 11.08V12C22 17.5228 17.5228 22 12 22C6.47715 22 2 17.5228 2 12C2 6.47715 6.47715 2 12 2C12.8284 2 13.6328 2.07407 14.4142 2.21651" stroke="white" stroke-width="2" stroke-linecap="round"/>
            <path d="M12 6V12L16 14" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
        </svg>
        <span id="notificationText">操作成功</span>
    </div>

    <script>
        // 获取DOM元素
        const numInput = document.getElementById('numInput');
        const colorInput = document.getElementById('colorInput');
        const colorValueInput = document.getElementById('colorValue');
        const sizeInput = document.getElementById('sizeInput');
        const sizeDisplay = document.getElementById('sizeDisplay');
        const preview = document.getElementById('preview');
        const centerCircle = document.getElementById('centerCircle');
        const ripples = document.querySelectorAll('.ripple');
        const exportBtn = document.getElementById('exportBtn');
        const copyBtn = document.getElementById('copyBtn');
        const notification = document.getElementById('notification');
        const notificationText = document.getElementById('notificationText');
        const shapeOptions = document.querySelectorAll('.shape-option');
        
        // 当前选中的波纹形状
        let currentShape = 'circle';
        
        // 验证颜色格式
        function isValidColor(color) {
            // 检查是否为有效的十六进制颜色
            const hexRegex = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/;
            return hexRegex.test(color);
        }
        
        // 修复颜色格式
        function fixColorFormat(color) {
            // 如果是3位十六进制颜色，转换为6位
            if (/^#([A-Fa-f0-9]{3})$/.test(color)) {
                const r = color[1];
                const g = color[2];
                const b = color[3];
                return `#${r}${r}${g}${g}${b}${b}`;
            }
            // 如果没有#号但长度是3或6，添加#号
            if (/^([A-Fa-f0-9]{3}|[A-Fa-f0-9]{6})$/.test(color)) {
                return `#${color}`;
            }
            return null;
        }
        
        // 更新预览
        function updatePreview() {
            const number = numInput.value;
            const color = colorInput.value;
            const size = parseInt(sizeInput.value);
            
            // 更新预览区域尺寸
            preview.style.width = `${size}px`;
            preview.style.height = `${size}px`;
            
            // 更新中心圆尺寸和数字
            const circleSize = Math.max(size * 0.5, 20); // 确保最小尺寸为20
            centerCircle.style.width = `${circleSize}px`;
            centerCircle.style.height = `${circleSize}px`;
            centerCircle.style.fontSize = `${Math.max(circleSize * 0.4, 8)}px`; // 确保最小字体为8px
            centerCircle.textContent = number;
            
            // 更新颜色
            centerCircle.style.background = color;
            ripples.forEach(ripple => {
                ripple.style.borderColor = color;
            });
            
            // 更新尺寸显示
            sizeDisplay.textContent = `${size}px`;
            
            // 更新颜色值显示
            colorValueInput.value = color;
            
            // 更新波纹形状
            updateRippleShape(currentShape);
        }
        
        // 更新波纹形状
        function updateRippleShape(shape) {
            // 移除所有旧的形状类
            ripples.forEach(ripple => {
                ripple.className = ripple.className.replace(/shape-(circle|square|triangle|hexagon)/g, '');
                ripple.classList.add(`shape-${shape}`);
            });
        }
        
        // 导出图片
        function exportImage() {
            // 创建一个临时canvas来绘制当前状态
            const tempCanvas = document.createElement('canvas');
            const size = parseInt(sizeInput.value);
            tempCanvas.width = size;
            tempCanvas.height = size;
            const tempCtx = tempCanvas.getContext('2d');
            
            // 绘制白色背景
            tempCtx.fillStyle = '#ffffff';
            tempCtx.fillRect(0, 0, size, size);
            
            const centerX = size / 2;
            const centerY = size / 2;
            const circleSize = Math.max(size * 0.5, 20);
            const color = colorInput.value;
            const number = numInput.value;
            
            // 绘制中心形状
            tempCtx.fillStyle = color;
            tempCtx.beginPath();
            
            // 根据当前形状绘制中心图形
            if (currentShape === 'circle') {
                tempCtx.arc(centerX, centerY, circleSize / 2, 0, Math.PI * 2);
            } else if (currentShape === 'square') {
                const halfSize = circleSize / 2;
                tempCtx.rect(centerX - halfSize, centerY - halfSize, circleSize, circleSize);
            } else if (currentShape === 'triangle') {
                const halfSize = circleSize / 2;
                tempCtx.moveTo(centerX, centerY - halfSize);
                tempCtx.lineTo(centerX - halfSize, centerY + halfSize);
                tempCtx.lineTo(centerX + halfSize, centerY + halfSize);
                tempCtx.closePath();
            } else if (currentShape === 'hexagon') {
                drawHexagon(tempCtx, centerX, centerY, circleSize / 2);
            }
            
            tempCtx.fill();
            
            // 绘制数字
            tempCtx.fillStyle = 'white';
            tempCtx.font = `bold ${Math.max(circleSize * 0.4, 8)}px Arial`;
            tempCtx.textAlign = 'center';
            tempCtx.textBaseline = 'middle';
            tempCtx.fillText(number, centerX, centerY);
            
            // 绘制波纹效果
            for (let i = 0; i < 3; i++) {
                const progress = (Date.now() / 1000 + i * 0.66) % 2; // 模拟动画进度
                const radius = (circleSize / 2) * (0.5 + progress * 0.7);
                const opacity = 1 - progress / 2;
                
                tempCtx.strokeStyle = color;
                tempCtx.globalAlpha = opacity * 0.6;
                tempCtx.lineWidth = 2;
                tempCtx.beginPath();
                
                // 根据当前形状绘制波纹
                if (currentShape === 'circle') {
                    tempCtx.arc(centerX, centerY, radius, 0, Math.PI * 2);
                } else if (currentShape === 'square') {
                    tempCtx.rect(centerX - radius, centerY - radius, radius * 2, radius * 2);
                } else if (currentShape === 'triangle') {
                    tempCtx.moveTo(centerX, centerY - radius);
                    tempCtx.lineTo(centerX - radius, centerY + radius);
                    tempCtx.lineTo(centerX + radius, centerY + radius);
                    tempCtx.closePath();
                } else if (currentShape === 'hexagon') {
                    drawHexagon(tempCtx, centerX, centerY, radius);
                }
                
                tempCtx.stroke();
            }
            tempCtx.globalAlpha = 1;
            
            // 创建下载链接
            const link = document.createElement('a');
            link.download = `波纹数字-${number}.png`;
            link.href = tempCanvas.toDataURL('image/png');
            document.body.appendChild(link);
            link.click();
            document.body.removeChild(link);
            
            // 显示通知
            showNotification('图片已导出');
        }
        
        // 生成SVG代码（兼容公众号编辑器）
        function generateSVG() {
            const size = parseInt(sizeInput.value);
            const color = colorInput.value;
            const number = numInput.value;
            const circleSize = Math.max(size * 0.5, 20);
            const fontSize = Math.max(circleSize * 0.4, 8);
            
            // 计算波纹相关参数
            const maxRadius = size / 2; // 最大半径
            const startRadius = maxRadius * 0.5; // 起始半径
            const radiusDiff = maxRadius * 0.7; // 半径变化量
            
            // 生成中心形状的SVG代码
            let centerShape = '';
            if (currentShape === 'circle') {
                centerShape = `<circle cx="${size/2}" cy="${size/2}" r="${circleSize/2}" fill="${color}"/>`;
            } else if (currentShape === 'square') {
                const halfSize = circleSize / 2;
                centerShape = `<rect x="${size/2 - halfSize}" y="${size/2 - halfSize}" width="${circleSize}" height="${circleSize}" fill="${color}"/>`;
            } else if (currentShape === 'triangle') {
                const halfSize = circleSize / 2;
                centerShape = `<path d="M ${size/2} ${size/2 - halfSize} L ${size/2 - halfSize} ${size/2 + halfSize} L ${size/2 + halfSize} ${size/2 + halfSize} Z" fill="${color}"/>`;
            } else if (currentShape === 'hexagon') {
                // 生成六边形路径
                let hexPath = `M `;
                for (let i = 0; i < 6; i++) {
                    const angle = i * Math.PI / 3 - Math.PI / 6;
                    const x = size/2 + (circleSize/2) * Math.cos(angle);
                    const y = size/2 + (circleSize/2) * Math.sin(angle);
                    hexPath += `${x} ${y} `;
                }
                hexPath += `Z`;
                centerShape = `<path d="${hexPath}" fill="${color}"/>`;
            }
            
            // 生成波纹形状的SVG代码
            let rippleShapes = '';
            if (currentShape === 'circle') {
                // 圆形波纹
                for (let i = 0; i < 3; i++) {
                    const delay = i * 0.66;
                    rippleShapes += `
    <!-- 波纹${i+1} ${delay > 0 ? `- 延迟${delay}秒` : ''} -->
    <circle cx="${size/2}" cy="${size/2}" r="${startRadius}" fill="none" stroke="${color}" stroke-width="2">
      <animate attributeName="r" from="${startRadius}" to="${startRadius + radiusDiff}" dur="2s" ${delay > 0 ? `begin="${delay}s"` : ''} repeatCount="indefinite" />
      <animate attributeName="opacity" from="0.6" to="0" dur="2s" ${delay > 0 ? `begin="${delay}s"` : ''} repeatCount="indefinite" />
    </circle>`;
                }
            } else if (currentShape === 'square') {
                // 方形波纹
                for (let i = 0; i < 3; i++) {
                    const delay = i * 0.66;
                    rippleShapes += `
    <!-- 波纹${i+1} ${delay > 0 ? `- 延迟${delay}秒` : ''} -->
    <rect x="${size/2 - startRadius}" y="${size/2 - startRadius}" width="${startRadius * 2}" height="${startRadius * 2}" fill="none" stroke="${color}" stroke-width="2">
      <animate attributeName="width" from="${startRadius * 2}" to="${(startRadius + radiusDiff) * 2}" dur="2s" ${delay > 0 ? `begin="${delay}s"` : ''} repeatCount="indefinite" />
      <animate attributeName="height" from="${startRadius * 2}" to="${(startRadius + radiusDiff) * 2}" dur="2s" ${delay > 0 ? `begin="${delay}s"` : ''} repeatCount="indefinite" />
      <animate attributeName="x" from="${size/2 - startRadius}" to="${size/2 - (startRadius + radiusDiff)}" dur="2s" ${delay > 0 ? `begin="${delay}s"` : ''} repeatCount="indefinite" />
      <animate attributeName="y" from="${size/2 - startRadius}" to="${size/2 - (startRadius + radiusDiff)}" dur="2s" ${delay > 0 ? `begin="${delay}s"` : ''} repeatCount="indefinite" />
      <animate attributeName="opacity" from="0.6" to="0" dur="2s" ${delay > 0 ? `begin="${delay}s"` : ''} repeatCount="indefinite" />
    </rect>`;
                }
            } else if (currentShape === 'triangle') {
                // 三角形波纹 - 使用基本的animate元素替代animateTransform
                for (let i = 0; i < 3; i++) {
                    const delay = i * 0.66;
                    // 计算三角形的三个顶点
                    const topY = size/2 - startRadius;
                    const bottomY = size/2 + startRadius;
                    const leftX = size/2 - startRadius;
                    const rightX = size/2 + startRadius;
                    
                    // 计算缩放后的顶点
                    const scaleFactor = (startRadius + radiusDiff) / startRadius;
                    const scaledTopY = size/2 - (startRadius + radiusDiff);
                    const scaledBottomY = size/2 + (startRadius + radiusDiff);
                    const scaledLeftX = size/2 - (startRadius + radiusDiff);
                    const scaledRightX = size/2 + (startRadius + radiusDiff);
                    
                    // 使用path动画替代scale变换
                    rippleShapes += `
    <!-- 波纹${i+1} ${delay > 0 ? `- 延迟${delay}秒` : ''} -->
    <path d="M ${size/2} ${topY} L ${leftX} ${bottomY} L ${rightX} ${bottomY} Z" fill="none" stroke="${color}" stroke-width="2">
      <animate attributeName="d" 
        from="M ${size/2} ${topY} L ${leftX} ${bottomY} L ${rightX} ${bottomY} Z" 
        to="M ${size/2} ${scaledTopY} L ${scaledLeftX} ${scaledBottomY} L ${scaledRightX} ${scaledBottomY} Z" 
        dur="2s" ${delay > 0 ? `begin="${delay}s"` : ''} repeatCount="indefinite" />
      <animate attributeName="opacity" from="0.6" to="0" dur="2s" ${delay > 0 ? `begin="${delay}s"` : ''} repeatCount="indefinite" />
    </path>`;
                }
            } else if (currentShape === 'hexagon') {
                // 六边形波纹 - 使用基本的animate元素替代animateTransform
                let hexPath = `M `;
                let scaledHexPath = `M `;
                for (let i = 0; i < 6; i++) {
                    const angle = i * Math.PI / 3 - Math.PI / 6;
                    const x = size/2 + startRadius * Math.cos(angle);
                    const y = size/2 + startRadius * Math.sin(angle);
                    hexPath += `${x} ${y} `;
                    
                    // 计算缩放后的顶点
                    const scaledX = size/2 + (startRadius + radiusDiff) * Math.cos(angle);
                    const scaledY = size/2 + (startRadius + radiusDiff) * Math.sin(angle);
                    scaledHexPath += `${scaledX} ${scaledY} `;
                }
                hexPath += `Z`;
                scaledHexPath += `Z`;
                
                for (let i = 0; i < 3; i++) {
                    const delay = i * 0.66;
                    rippleShapes += `
    <!-- 波纹${i+1} ${delay > 0 ? `- 延迟${delay}秒` : ''} -->
    <path d="${hexPath}" fill="none" stroke="${color}" stroke-width="2">
      <animate attributeName="d" 
        from="${hexPath}" 
        to="${scaledHexPath}" 
        dur="2s" ${delay > 0 ? `begin="${delay}s"` : ''} repeatCount="indefinite" />
      <animate attributeName="opacity" from="0.6" to="0" dur="2s" ${delay > 0 ? `begin="${delay}s"` : ''} repeatCount="indefinite" />
    </path>`;
                }
            }
            
            // SVG内容，使用SMIL动画替代CSS动画（兼容公众号编辑器）
            const svgContent = `
<svg width="${size}" height="${size}" viewBox="0 0 ${size} ${size}" xmlns="http://www.w3.org/2000/svg">
  <!-- 中心形状 -->
  ${centerShape}
  
  <!-- 数字 -->
  <text x="${size/2}" y="${size/2}" font-family="Arial, sans-serif" font-weight="bold" font-size="${fontSize}" fill="white" text-anchor="middle" dominant-baseline="middle">${number}</text>
  
  <!-- 波纹效果 - 使用SMIL动画 -->
  <g>
    ${rippleShapes}
  </g>
</svg>
            `.trim();
            
            return svgContent;
        }
        
        // 复制SVG代码到剪贴板
        function copySVG() {
            try {
                const svgCode = generateSVG();
                
                // 方案1: 使用Clipboard API (现代浏览器)
                if (navigator.clipboard) {
                    navigator.clipboard.writeText(svgCode).then(() => {
                        showNotification('SVG代码已复制到剪贴板');
                    }).catch(err => {
                        console.error('Clipboard API 失败:', err);
                        // 尝试降级方案
                        tryFallbackCopyText(svgCode);
                    });
                } else {
                    // 直接尝试降级方案
                    tryFallbackCopyText(svgCode);
                }
            } catch (err) {
                console.error('复制SVG失败:', err);
                showNotification('复制SVG失败，请重试', true);
            }
        }
        
        // 降级方案：复制文本
        function tryFallbackCopyText(text) {
            try {
                // 创建一个文本区域
                const textarea = document.createElement('textarea');
                textarea.value = text;
                textarea.style.position = 'absolute';
                textarea.style.left = '-9999px';
                document.body.appendChild(textarea);
                
                // 选中并复制
                textarea.select();
                const successful = document.execCommand('copy');
                
                // 清理
                document.body.removeChild(textarea);
                
                if (successful) {
                    showNotification('SVG代码已复制到剪贴板');
                } else {
                    throw new Error('execCommand返回false');
                }
            } catch (err) {
                console.error('降级方案失败:', err);
                showNotification('复制功能不可用，请手动复制下方代码', true);
                
                // 显示代码供用户手动复制
                showCodeDialog(text);
            }
        }
        
        // 显示代码对话框供用户手动复制
        function showCodeDialog(code) {
            // 创建对话框
            const dialog = document.createElement('div');
            dialog.style.position = 'fixed';
            dialog.style.top = '50%';
            dialog.style.left = '50%';
            dialog.style.transform = 'translate(-50%, -50%)';
            dialog.style.backgroundColor = 'white';
            dialog.style.padding = '20px';
            dialog.style.borderRadius = '8px';
            dialog.style.boxShadow = '0 5px 15px rgba(0, 0, 0, 0.2)';
            dialog.style.zIndex = '1001';
            dialog.style.maxWidth = '80%';
            dialog.style.maxHeight = '80%';
            dialog.style.overflow = 'auto';
            
            // 创建标题
            const title = document.createElement('h3');
            title.textContent = 'SVG代码 (请手动复制)';
            title.style.marginBottom = '15px';
            title.style.color = '#2c3e50';
            
            // 创建代码区域
            const codeArea = document.createElement('pre');
            codeArea.style.backgroundColor = '#f8f9fa';
            codeArea.style.padding = '15px';
            codeArea.style.borderRadius = '6px';
            codeArea.style.overflowX = 'auto';
            codeArea.style.fontFamily = 'monospace';
            codeArea.style.fontSize = '14px';
            codeArea.textContent = code;
            
            // 创建关闭按钮
            const closeBtn = document.createElement('button');
            closeBtn.textContent = '关闭';
            closeBtn.style.marginTop = '15px';
            closeBtn.style.padding = '8px 16px';
            closeBtn.style.backgroundColor = '#3498db';
            closeBtn.style.color = 'white';
            closeBtn.style.border = 'none';
            closeBtn.style.borderRadius = '4px';
            closeBtn.style.cursor = 'pointer';
            closeBtn.addEventListener('click', () => {
                document.body.removeChild(dialog);
                document.body.removeChild(overlay);
            });
            
            // 创建遮罩层
            const overlay = document.createElement('div');
            overlay.style.position = 'fixed';
            overlay.style.top = '0';
            overlay.style.left = '0';
            overlay.style.width = '100%';
            overlay.style.height = '100%';
            overlay.style.backgroundColor = 'rgba(0, 0, 0, 0.5)';
            overlay.style.zIndex = '1000';
            
            // 组装对话框
            dialog.appendChild(title);
            dialog.appendChild(codeArea);
            dialog.appendChild(closeBtn);
            
            // 添加到页面
            document.body.appendChild(overlay);
            document.body.appendChild(dialog);
            
            // 自动选中代码
            const range = document.createRange();
            range.selectNodeContents(codeArea);
            const selection = window.getSelection();
            selection.removeAllRanges();
            selection.addRange(range);
        }
        // 显示通知
        function showNotification(message, isError = false) {
            notificationText.textContent = message;
            
            // 移除之前的类
            notification.classList.remove('show', 'error');
            
            // 添加适当的类
            if (isError) {
                notification.classList.add('error');
            }
            
            // 显示通知
            setTimeout(() => {
                notification.classList.add('show');
                
                // 3秒后隐藏
                setTimeout(() => {
                    notification.classList.remove('show');
                }, 3000);
            }, 10);
        }
        
        // 处理颜色输入变化 - 简化版
        function handleColorInputChange() {
            let color = colorValueInput.value.trim();
            
            // 尝试修复颜色格式
            const fixedColor = fixColorFormat(color);
            
            if (fixedColor && isValidColor(fixedColor)) {
                colorValueInput.value = fixedColor;
                colorInput.value = fixedColor;
                updatePreview();
            } else if (isValidColor(color)) {
                colorInput.value = color;
                updatePreview();
            } else {
                // 如果输入的颜色无效，不做任何操作，保留用户输入
                // 这样用户可以继续编辑，而不是立即恢复
                return;
            }
        }
        
        // 处理颜色选择器变化
        function handleColorPickerChange() {
            colorValueInput.value = colorInput.value;
            updatePreview();
        }
        
        // 处理颜色输入框的输入事件
        function handleColorValueKeyDown(e) {
            // 允许用户自由输入，不做特殊处理
            // 用户可以直接输入#号，或者其他字符
        }
        
        // 初始化事件监听
        numInput.addEventListener('input', updatePreview);
        colorInput.addEventListener('input', handleColorPickerChange);
        
        // 使用标准的事件监听方式
        colorValueInput.addEventListener('input', handleColorInputChange);
        colorValueInput.addEventListener('blur', handleColorInputChange);
        colorValueInput.addEventListener('keydown', handleColorValueKeyDown);
        
        sizeInput.addEventListener('input', updatePreview);
        exportBtn.addEventListener('click', exportImage);
        copyBtn.addEventListener('click', copySVG);
        
        // 形状选择事件
        shapeOptions.forEach(option => {
            option.addEventListener('click', () => {
                // 移除所有选项的active类
                shapeOptions.forEach(opt => opt.classList.remove('active'));
                
                // 添加当前选项的active类
                option.classList.add('active');
                
                // 更新当前形状
                currentShape = option.dataset.shape;
                
                // 更新预览
                updatePreview();
            });
        });
        
        // 初始预览
        updatePreview();
        
        
        
        // 绘制六边形
        function drawHexagon(ctx, cx, cy, radius) {
            ctx.beginPath();
            for (let i = 0; i < 6; i++) {
                const angle = i * Math.PI / 3 - Math.PI / 6;
                const x = cx + radius * Math.cos(angle);
                const y = cy + radius * Math.sin(angle);
                if (i === 0) {
                    ctx.moveTo(x, y);
                } else {
                    ctx.lineTo(x, y);
                }
            }
            ctx.closePath();
        }
    </script>
</body>
</html>